<template>
	<component
		:is="detail === false ? ElSelect : 'div'"
		v-model="fieldValue"
		collapse-tags-tooltip
		collapse-tags
		clearable
		filterable
		@change="selectChange"
		v-bind="$attrs"
	>
		<slot>
			<template v-if="detail === false">
				<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" :disabled="item.disabled" />
			</template>
			<template v-else>
				{{ selectDictLabel(options, fieldValue, ',', { dictValue: 'value', dictLabel: 'label' }) }}
			</template>
		</slot>
		<template v-for="(slotKey, slotIndex) in Object.keys($slots)" :key="slotIndex" v-slot:[slotKey]>
			<slot :name="slotKey"></slot>
		</template>
	</component>
</template>

<script setup name="MySelect">
import { API_HOST } from '@/config';
import axios from '@u/axios';
import _camelCase from 'lodash/camelCase';

const ElSelect = defineAsyncComponent(() => import('element-plus').then((mod) => mod['ElSelect'])),
	emits = defineEmits(['update:modelValue', 'getLabel', 'getRow']);
/***
 * 参数属性
 * @property {Object[]} modelValue 默认值
 * @property {list[]} list 下拉列表数据
 * @property {Boolean} needAll 是否需要全部选项，默认为false
 * @property {Object} fillType 数据格式默认为{ label: 'dictLabel', value: 'dictValue' }
 * @property {Function} loadmoreFn 滚动加载的方法，loadmoreFn传入时popper-append-to-body为false
 * @property {String} type store.dispatch的方法名,兼容'GETdeptTree'/'deptTree'/'dept_tree'三种方式
 * @property {String，Function} api 数据请求地址，默认请求为·GET·方式，支持传递url地址、api请求方法两种
 * @property {Boolean} original 是否保留原始数据，默认为false
 * @property {Boolean} detail 是否为详情展示形式，默认为false
 */
const props = defineProps({
	modelValue: {},
	list: {
		type: Array,
		default: () => []
	},
	needAll: {
		type: Boolean,
		default: false
	},
	fileType: {
		type: Object,
		default: () => ({ label: 'dictLabel', value: 'dictValue' })
	},
	loadmoreFn: {
		type: Function
	},
	type: {
		type: String
	},
	api: {
		type: [String, Function]
	},
	original: {
		type: Boolean,
		default: false
	},
	detail: {
		type: Boolean,
		default: false
	}
});

const options = ref([]),
	fieldValue = computed({
		get() {
			if (typeof props.modelValue === 'number') return `${props.modelValue}`;
			return props.modelValue;
		},
		set(val) {
			emits('update:modelValue', val);
		}
	}),
	dictType = computed(() => _camelCase(props.type));

/**
 * 获取选中的label
 * 获取选中的对象值
 * @param {*} val
 */
function selectChange(val) {
	emits('getLabel', unref(options).find((item) => item.value === val)?.label);
	emits(
		'getRow',
		unref(options).find((item) => item.value === val)
	);
}
/**
 * 数据处理
 * @param {[]} data 原始数据
 * @param {} fileType 处理{ label: 'dictLabel', value: 'dictValue' }对象
 */
function fileTypeFn(data, fileType = props.fileType) {
	return data.map((val) => {
		const obj = {
			label: val[fileType.label],
			value: val[fileType.value],
			disabled: val[fileType.disabled] || false
		};
		if (props.original) {
			return {
				...obj,
				...val
			};
		} else {
			return obj;
		}
	});
}
/**
 * 添加全部选项
 * @param {*} data 原始数据
 */
function needAllFn(data) {
	const num = JSON.stringify(data).includes(JSON.stringify({ label: '全部', value: '' }));
	if (!num) data.unshift({ label: '全部', value: '' });
	return data;
}

function initialization(list = props.list) {
	options.value = fileTypeFn(list);
	if (props.needAll) options.value = needAllFn(options.value);
}
watch(
	() => props.list,
	(val) => {
		if (Array.isArray(val)) initialization(val);
	},
	{ deep: true, immediate: true }
);

watch(
	() => $store?.dict[dictType.value] || $store?.com[dictType.value],
	(val) => {
		if (dictType.value) initialization(val);
	},
	{ deep: true, immediate: true }
);

watch(
	() => props.api,
	(val) => {
		if (val) {
			if (typeof val === 'string') {
				axios({
					method: 'get',
					url: API_HOST + val
				}).then((res) => {
					initialization(res.data || []);
				});
			}
			if (typeof val === 'function') {
				val().then((res) => {
					initialization(res.data || []);
				});
			}
		}
	},
	{ immediate: true }
);

// 初始化执行逻辑
function initFn() {
	if (dictType.value) {
		if ($store.dict[dictType.value]) return $store.dict[`GET${dictType.value}`]();
		if ($store.com[dictType.value]) return $store.com[`GET${dictType.value}`]();
		throw new Error('字典数据未添加！');
	} else {
		initialization();
	}
}
watch(
	() => dictType.value,
	(val) => {
		if (val) initFn();
	},
	{ immediate: true }
);
</script>

<style lang="scss" scoped>
:deep(.el-select) {
	width: 100%;
}
</style>
